package io.geekidea.boot.framework.page;


import io.geekidea.boot.framework.entity.BaseVO;
import io.geekidea.boot.framework.exception.BusinessException;
import io.geekidea.boot.framework.exception.ResponseCode;
import io.geekidea.boot.framework.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author shusong.liang
 */
@Slf4j
public class PageUtils {


    public static <T> PageResponse<T> handlePageToResponse(Page<T> data) {
        PageResponse<T> pageResponse = new PageResponse<>();
        if(Objects.nonNull(data) && !data.isEmpty()){
            pageResponse.setData(data.getContent());
            pageResponse.setTotalCount(data.getTotalElements());
            pageResponse.setTotalPage(data.getTotalPages());

            Pageable pageable = data.getPageable();
            pageResponse.setPageNum(pageable.getPageNumber());
            pageResponse.setPageSize(pageable.getPageSize());
        }
        pageResponse.setFirstId("");
        pageResponse.setLastId("");
        return pageResponse;
    }


    /**
     * 默认的起始坐标
     */
    private static final int DEFAULT_START = 0;

    public static <T> PageResponse<T> defaultResponse() {
        PageResponse<T> pageResponse = new PageResponse<>();
        pageResponse.setData(new ArrayList<>());
        pageResponse.setFirstId("");
        pageResponse.setLastId("");
        pageResponse.setPageSize(0);
        return pageResponse;
    }

    /**
     * 内存分页, 适用于数据量较小的时候一次性加载数据到 JVM中做分页
     * @param pageNum 页号
     * @param pageSize 页面大小
     * @param list 数据集合
     * @param <T> 实体对象
     * @return
     */
    public static <T> PageResponse<T> getPageInMemory(final Integer pageNum,
            final int pageSize, List<T> list) {

        // 初始化 pageNum和 pageSize
        int pNum = (pageNum == null || pageNum < 1) ? PageRequest.DEFAULT_PAGE_NUM : pageNum;
        int pSize = pageSize < 1 ? PageRequest.DEFAULT_PAGE_SIZE : pageSize;

        final int total = list.size();
        if (total == 0) {
            PageResponse<T> emptyPage = new PageResponse<>();
            emptyPage.setPageNum(pNum);
            emptyPage.setPageSize(pSize);
            emptyPage.setTotalCount(0L);
            emptyPage.setTotalPage(0);
            emptyPage.setData(new ArrayList<>());
            return emptyPage;
        }

        // 集合分割索引
        int startIndex = (pNum - 1) * pSize;
        int end = startIndex + pSize;

        startIndex = startIndex > total ? DEFAULT_START : startIndex;
        end = end > total ? total : end;

        PageResponse<T> pageResponse = new PageResponse<>();
        pageResponse.setTotalCount((long) total);
        pageResponse.setPageNum(pNum);
        pageResponse.setPageSize(pSize);

        pageResponse.setTotalPage((int) (Math.ceil(total / (double) pSize)));
        pageResponse.setData(list.subList(startIndex ,end));
        return pageResponse;
    }

    /**
     *@Description: 基于上下翻的内存分页
     *@param: [pageRequest, list]
     *@return: com.zhirui.dbpick.common.PageResponse<com.zhirui.dbpick.common.domain.AbstractVO>
     *@throws:
     *
     *@author  shusong.liang
     *@dateTime  2019/4/30 16:10
    */
    public static <T extends BaseVO> PageResponse<T> getPageInMemoryByScroll(PageRequest pageRequest,
                                                                             List<T> list) throws Exception {
         if(CollectionUtils.isEmpty(list)){
             return defaultResponse();
         }
         //热门条数
         int hotSize = list.size();

         //封装数据
         String firstId = pageRequest.getFirstId();
         String lastId = pageRequest.getLastId();
         //获取第一个id和最后一个id对应数据的下标
         int firstIndex = 0;
         int lastIndex = 0;
         for (int i = 0; i < list.size(); i++) {
             if(StringUtils.isNotBlank(firstId)
                     && list.get(i).getId().equals(firstId)){
                 firstIndex = i;
             }
             if(StringUtils.isNotBlank(lastId)
                     && list.get(i).getId().equals(lastId)){
                 lastIndex = i;
             }
         }
         //容量
         int pageSize = pageRequest.getPageSize();
         //方向 向上：1  向下：2
         int direction = pageRequest.getDirection();
         //截取起始下标
         int startIndex = 0;
         //截取终止下标
         int endIndex;
         switch (direction) {
             case PageRequest.PageDirection.PREVIOUS:
                 if (StringUtils.isBlank(firstId)) {
                     log.error("Page Query NEXT, firstId is empty");
                     throw new BusinessException("firstId为空", ResponseCode.FAILED);
                 }
                 //上一批第一条数据作为终止下标
                 endIndex = firstIndex;
                 //往前倒推指定条数作为起始下标
                 startIndex = endIndex - pageSize;

                 break;
             case PageRequest.PageDirection.NEXT:
                 //两id都为空说明是首次加载
                if(StringUtils.isBlank(firstId) && StringUtils.isBlank(lastId)){
                    //默认向下查指定条数
                    endIndex = pageSize;
                }else{
                    if (StringUtils.isBlank(lastId)) {
                        log.error("Page Query NEXT, lastId is empty");
                        throw new BusinessException("lastId为空", ResponseCode.FAILED);
                    }
                    //上一批最后一条数据作为起始下标
                    startIndex = lastIndex + 1;
                    //起始加上条数作为终止下标
                    endIndex = startIndex + pageSize;
                }
                 break;
             default:
                 //默认不传，向下查指定条数
                 endIndex = pageSize;
                 break;
         }
         //更正下标 防止越界
         startIndex = startIndex < 0 ? 0 : startIndex;
         endIndex = endIndex > hotSize ? hotSize: endIndex;
         //截取
         list = list.subList(startIndex, endIndex);

         //构造分页返回值
         PageResponse<T> pageResponse = new PageResponse<>();
         pageResponse.setData(list);

         if (!CollectionUtils.isEmpty(list)) {
             //设置id
             pageResponse.setFirstId(list.get(0).getId());
             pageResponse.setLastId(list.get(list.size() - 1).getId());
             pageResponse.setPageSize(list.size());
         }

         return pageResponse;
     }

//   public static void main(String[] args) {
//        List<Integer> collect = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toList());
//
//
////        System.out.println(getPageInMemory(1, 2, collect));
////        System.out.println(getPageInMemory(2, 2, collect));
////        System.out.println(getPageInMemory(3, 3, collect));
//        System.out.println(collect.subList(1,5));
//    }

}
